package cn.mujiankeji.mbrowser.界面.小窗页

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import cn.mujiankeji.mbrowser.数据.数据库.DBSearchEngine
import cn.mujiankeji.mbrowser.数据.数据库.AppDatabase

import cn.mujiankeji.mbrowser.界面.图标.MyIconPack
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.关闭
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.搜索
import cn.mujiankeji.mbrowser.界面.框架.小窗视图.小窗状态
import cn.mujiankeji.mbrowser.app.界面模块
import cn.mujiankeji.mbrowser.界面.组件.按钮.水平标签
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.koin.compose.koinInject
import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.TextRange
import cn.mujiankeji.mbrowser.app.应用接口
import cn.mujiankeji.mbrowser.工具.mlog
import cn.mujiankeji.mbrowser.工具.网络.网络操作
import cn.mujiankeji.mbrowser.数据.配置项.应用配置
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.graphics.vector.ImageVector
import cn.mujiankeji.mbrowser.app.应用路由
import cn.mujiankeji.mbrowser.工具.操作.地址操作
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.书签
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.历史
import cn.mujiankeji.mbrowser.界面.标签页.主页.主页标签状态
import cn.mujiankeji.mbrowser.界面.标签页.聚搜.聚搜页面状态
import cn.mujiankeji.mbrowser.界面.框架.主视图.标签页状态
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import org.json.JSONException
import org.json.JSONObject



/**
 * 页面的搜索、网址详情等综合窗口。 用的最频繁的视图
 */
class 详情输入小窗页面状态() : 小窗状态()
{
    var coroutine : CoroutineScope ?= null
    var 选中搜索引擎 by mutableStateOf<DBSearchEngine?>(null) // 使用 id 而非对象
    var 输入中内容 by mutableStateOf(TextFieldValue(""))
    var 输入框焦点 = FocusRequester()
    var 输入内容类型 by mutableStateOf(输入内容类型枚举.无)
    var 显示搜索引擎 by mutableStateOf(false)
    var 页面地址 = ""
    var 页面关键词 : String ?= null

    fun 插入内容(str: String) {
        val currentText = 输入中内容.text
        val selection = 输入中内容.selection
        var insertStr = str
        // 只要是以.开头且长度大于2的内容，都视为域名后缀
        if (str.startsWith(".") && str.length > 2) {
            val insertPos = selection.start
            if (insertPos > 0 && currentText.getOrNull(insertPos - 1) == '.') {
                insertStr = str.removePrefix(".")
            }
        }
        val newText = if (selection.collapsed) {
            currentText.substring(0, selection.start) + insertStr + currentText.substring(selection.start)
        } else {
            currentText.substring(0, selection.min) + insertStr + currentText.substring(selection.max)
        }
        val newSelectionStart = if (selection.collapsed) {
            selection.start + insertStr.length
        } else {
            selection.min + insertStr.length
        }
        输入中内容 = TextFieldValue(
            text = newText,
            selection = androidx.compose.ui.text.TextRange(newSelectionStart)
        )
    }
    fun 切换引擎(eng : DBSearchEngine){
        选中搜索引擎 = eng
    }
    fun 提交(){
        coroutine?.launch {
            val keyword = 输入中内容.text.trim()
            if (keyword.isEmpty()) return@launch
            if (输入内容类型 == 输入内容类型枚举.地址) {
                应用路由.加载(keyword)
            }
            else if (输入内容类型 == 输入内容类型枚举.关键词){
                val viewState = vm()?:return@launch
                val engine = 选中搜索引擎
                if (engine == null || engine.地址列表.isEmpty()) {
                    viewState.加载(应用配置.默认搜索地址(keyword))
                }
                else if (engine.地址列表.size == 1) {
                    val searchItem = engine.地址列表.first()
                    val urlToLoad = searchItem.地址.replaceFirst("%s", Uri.encode(keyword))
                    viewState.加载(urlToLoad)
                }
                else {
                    // 创建聚合搜索页面，传递搜索引擎和关键词
                    应用路由.加载(聚搜页面状态(keyword = keyword, searchEngine = engine))
                }
            }

        }
        // 不管内容为什么，都关闭小窗
        应用接口.关闭小窗()
    }
    fun 可能是域名或地址(text: String): Boolean {
        val trimmed = text.trim()
        if (trimmed.isEmpty()) return false
        // 网址前缀
        if (trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("ftp://")) return true
        // 域名
        if (Regex("^[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$").matches(trimmed)) return true
        // IP
        if (Regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}$").matches(trimmed)) return true
        return false
    }

}

@Composable
fun 搜索输入窗口实现(state : 详情输入小窗页面状态, viewState: 界面模块 = koinInject<界面模块>()){

    state.coroutine = rememberCoroutineScope()
    DisposableEffect(Unit) {
        onDispose {
            state.coroutine = null
        }
    }

    LaunchedEffect(viewState.当前标签页) {
        val p = viewState.当前标签页 ?: return@LaunchedEffect
        if (p !is 主页标签状态){
            state.页面地址 = p.地址.first()?:""
            state.页面关键词 = p.关键词
            val k = state.页面关键词?:state.页面地址
            state.输入中内容 = TextFieldValue(k, TextRange(0,k.length))

        }

    }


    Column(Modifier.fillMaxSize()
        .background(MaterialTheme.colorScheme.surface))
    {

        // 小窗内容
        LazyColumn(Modifier.weight(1f).fillMaxWidth(),
            reverseLayout = true) {
            item {
                辅助输入视图(state)
            }
        }


        // 输入栏
        输入栏(state)

        // 网址输入辅助、搜索引擎切换
        搜索引擎栏(state)

        // 输入法
        输入法视图(state)

    }

    // 默认选中
    LaunchedEffect(state.coroutine) {
        state.输入框焦点.requestFocus()
    }
}

/**
 * 辅助输入页面包含
 * 输入前-空地址：历史搜索记录
 * 输入前-含地址：复制地址选项
 * 输入过程：输入提示词、历史及书签记录匹配
 *
 */
@Composable
private fun 辅助输入视图(state: 详情输入小窗页面状态){
    val 输入文本 = state.输入中内容.text.trim()
    val 显示书签历史 = 应用配置.读取输入补全书签历史().collectAsState(true).value
    val 显示网络关键词 = 应用配置.读取输入补全网络关键词().collectAsState(true).value
    
    // 根据输入内容长度和类型决定显示什么内容
    when {
        // 当输入为空时
        输入文本.isEmpty() -> {
            // 可以显示最近的搜索历史或常用网站
            // 这里可以根据需求实现
        }
        
        // 当输入内容是URL时，优先显示书签和历史匹配
        state.输入内容类型 == 输入内容类型枚举.地址 && 显示书签历史 -> {
            书签历史补全(state)
        }
        
        // 当输入内容是关键词时
        state.输入内容类型 == 输入内容类型枚举.关键词 -> {
            // 首先尝试匹配书签和历史
            if (显示书签历史) {
                书签历史补全(state)
            }

            if (显示网络关键词) {
                百度关键词补全(state)
            }
        }
    }
}

// 创建一个CompositionLocal用于跟踪书签历史是否有结果
private val LocalBookmarkHistoryResultTracker = compositionLocalOf<MutableState<Boolean>> { 
    mutableStateOf(false) 
}

@Composable
private fun 百度关键词补全(state : 详情输入小窗页面状态){
    val keys = remember { mutableStateListOf<String>() }
    var isLoading by remember { mutableStateOf(false) }
    
    // 使用rememberUpdatedState包装输入内容，避免协程取消问题
    val 输入内容 = rememberUpdatedState(state.输入中内容.text.trim())

    // 使用唯一的key，确保当输入内容变化时协程被正确取消和重启
    val inputKey = remember(输入内容.value) { System.currentTimeMillis() }
    
    LaunchedEffect(inputKey) {
        val key = 输入内容.value
        mlog("key",key)

        // 当输入内容为空或太短时不进行请求
        if (key.length < 2) {
            keys.clear()
            return@LaunchedEffect
        }

        isLoading = true
        try {
            // 请求百度搜索建议API
            // API格式: http://suggestion.baidu.com/su?wd=关键词&p=3&cb=
            // 返回格式: ({q:"关键词",p:false,s:["建议1","建议2"...]});
            var json = 网络操作.获取文本("http://suggestion.baidu.com/su?wd=$key&p=3&cb=")

            // 解析返回的JSON
            if (!json.isNullOrEmpty()) {
                json = json.substring(1, json.length - 2) // 去除首尾括号
                try {
                    keys.clear()
                    val jsonObject = JSONObject(json)
                    val jsonArray = jsonObject.getJSONArray("s")
                    for (i in 0 until jsonArray.length()) {
                        keys.add(jsonArray[i] as String)
                    }
                }
                catch (e: JSONException) {
                    e.printStackTrace()
                    mlog("解析失败")
                }

            }
        } catch (e: Exception) {
            mlog("百度关键词补全请求失败", e.message ?: "未知错误")
        } finally {
            isLoading = false
        }
    }

    // 显示关键词建议列表
    if (keys.isNotEmpty() && state.输入中内容.text.isNotEmpty() && state.输入内容类型 == 输入内容类型枚举.关键词) {
        Column(
            Modifier
                .fillMaxWidth()
                .padding(horizontal = 10.dp, vertical = 5.dp)
        ) {
            keys.take(5).forEach { suggestion ->
                Row(
                    Modifier
                        .fillMaxWidth()
                        .clickable {
                            // 点击建议时，更新输入框内容
                            state.输入中内容 = TextFieldValue(
                                text = suggestion,
                                selection = TextRange(suggestion.length)
                            )
                        }
                        .padding(vertical = 8.dp, horizontal = 12.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Icon(
                        MyIconPack.搜索,
                        contentDescription = null,
                        modifier = Modifier.size(16.dp),
                        tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f)
                    )
                    Spacer(modifier = Modifier.width(8.dp))
                    Text(
                        text = suggestion,
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurface
                    )
                }
            }
        }
    }
}

@Composable
private fun 书签历史补全(state: 详情输入小窗页面状态){
    val database = koinInject<AppDatabase>()
    val 书签列表 = remember { mutableStateListOf<cn.mujiankeji.mbrowser.数据.数据库.DBBookmark>() }
    val 历史列表 = remember { mutableStateListOf<cn.mujiankeji.mbrowser.数据.数据库.DBHistory>() }
    
    // 使用rememberUpdatedState包装输入内容，避免协程取消问题
    val 搜索关键词 = rememberUpdatedState(state.输入中内容.text.trim())
    
    // 获取结果跟踪器（如果有）
    val resultTracker = LocalBookmarkHistoryResultTracker.current
    
    // 使用唯一的key，确保当输入内容变化时协程被正确取消和重启
    val inputKey = remember(搜索关键词.value) { System.currentTimeMillis() }
    
    // 当输入内容变化时，查询匹配的书签和历史记录
    LaunchedEffect(inputKey) {
        val keyword = 搜索关键词.value
        // 只有当输入长度大于1时才进行查询
        if (keyword.length > 1) {
            try {
                // 查询匹配的书签 - 修复参数数量问题
                database.书签().搜索书签(keyword).collect { results ->
                    书签列表.clear()
                    书签列表.addAll(results.take(5)) // 限制结果数量为5
                    
                    // 更新结果跟踪器
                    resultTracker.value = 书签列表.isNotEmpty() || 历史列表.isNotEmpty()
                }
                
                // 查询匹配的历史记录 - 修复方法名称
                database.历史().搜索历史记录(keyword).collect { results ->
                    历史列表.clear()
                    历史列表.addAll(results.take(5)) // 限制结果数量为5
                    
                    // 更新结果跟踪器
                    resultTracker.value = 书签列表.isNotEmpty() || 历史列表.isNotEmpty()
                }
            } catch (e: Exception) {
                mlog("书签历史查询失败", e.message ?: "未知错误")
            }
        } else {
            书签列表.clear()
            历史列表.clear()
            
            // 更新结果跟踪器
            resultTracker.value = false
        }
    }

    @Composable
    fun ColumnScope.item(title : String,url : String,icon : ImageVector){
        Row(
            Modifier
                .fillMaxWidth()
                .clickable {
                    // 点击书签时，直接加载该URL - 修复字段名
                    state.vm()?.加载(url)
                    state.vm()?.移除小窗(state)
                }
                .padding(vertical = 8.dp, horizontal = 12.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            // 显示书签图标
            Icon(icon, // 这里可以替换为书签图标
                contentDescription = null,
                modifier = Modifier.size(16.dp),
                tint = MaterialTheme.colorScheme.primary
            )

            Spacer(modifier = Modifier.width(8.dp))

            // 显示书签标题和URL - 修复字段名
            Column {
                Text(
                    text = title,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurface,
                    maxLines = 1
                )
                Text(
                    text = url,
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    maxLines = 1
                )
            }
        }
    }
    
    // 只有在输入模式为关键词或地址，且有查询结果时才显示
    if ((state.输入内容类型 == 输入内容类型枚举.关键词 || state.输入内容类型 == 输入内容类型枚举.地址) && 
        搜索关键词.value.isNotEmpty() && (书签列表.isNotEmpty() || 历史列表.isNotEmpty())) {
        
        Column(
            Modifier
                .fillMaxWidth()
                .padding(horizontal = 10.dp, vertical = 5.dp)
        ) {
            // 显示书签结果
            if (书签列表.isNotEmpty()) {
                书签列表.forEach { 书签 ->
                    item(书签.标题,书签.网址,MyIconPack.书签)
                }
                
                // 添加分隔线
                if (历史列表.isNotEmpty()) {
                    Spacer(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(1.dp)
                            .padding(horizontal = 12.dp)
                            .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
                    )
                }
            }
            
            // 显示历史记录结果
            if (历史列表.isNotEmpty()) {
                历史列表.forEach { 历史 ->
                    item(历史.标题,历史.网址,MyIconPack.历史)
                }
            }
        }
    }
}

@Composable
private fun 输入栏(state: 详情输入小窗页面状态){

    LaunchedEffect(state.输入中内容) {
        state.输入中内容.text.let {
            // TODO 根据关键词获取 state.输入内容类型
            if (it.isEmpty()) {
                state.输入内容类型 = 输入内容类型枚举.无
            } else if (it == state.页面地址 && state.页面地址.isNotEmpty()) {
                state.输入内容类型 = 输入内容类型枚举.原地址
            }
            else if (地址操作.isUrl(it)) {
                state.输入内容类型 = 输入内容类型枚举.地址
            }
            else {
                state.输入内容类型 = 输入内容类型枚举.关键词
                if (!state.显示搜索引擎){
                    state.显示搜索引擎 = !state.可能是域名或地址(it)
                }
            }
        }
    }

    Row(Modifier.fillMaxWidth()
        .height(50.dp)
        .padding(horizontal = 10.dp),
        verticalAlignment = Alignment.CenterVertically) {


        // 输入框
        Row(Modifier.weight(1f)
            .height(40.dp)
            .clip(MaterialTheme.shapes.medium)
            .background(MaterialTheme.colorScheme.surfaceVariant)
            .padding(horizontal = 5.dp),
            verticalAlignment = Alignment.CenterVertically)
        {

            // 搜索图标、切换输入法或网址输入
            IconButton({
                state.显示搜索引擎 = !state.显示搜索引擎
            }, modifier = Modifier.size(30.dp)){
                Icon(MyIconPack.搜索,"",
                    tint = if (state.显示搜索引擎) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.size(18.dp))
            }

            BasicTextField(state.输入中内容, onValueChange = {
                state.输入中内容 = it
            }, modifier = Modifier.weight(1f)
                .focusRequester(state.输入框焦点),
                maxLines = 1)


            // 若有输入内容，应当显示清理按钮
            if (state.输入中内容.text.isNotEmpty()){
                IconButton({
                    state.输入中内容 = TextFieldValue()
                }, modifier = Modifier.size(30.dp)) {
                    Icon(MyIconPack.关闭,"",
                        tint = MaterialTheme.colorScheme.secondary,
                        modifier = Modifier.size(16.dp))
                }
            }

        }

        Spacer(Modifier.width(10.dp))

        // 按钮
        Box(Modifier.fillMaxHeight()
            .clickable {
                state.提交()
            }
            .padding(horizontal = 10.dp),
            contentAlignment = Alignment.Center){
            Text(state.输入内容类型.到文本(),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant)
        }


    }

}

@Composable
private fun 搜索引擎栏(state: 详情输入小窗页面状态){
    val database = koinInject<AppDatabase>().搜索引擎()
    val engines = remember { mutableStateListOf<DBSearchEngine>() }

    LaunchedEffect(Unit) {
        // 默认最多仅显示20个搜索引擎
        database.获取搜索引擎(20).collect{
            engines.clear()
            engines.addAll(it)
            if (state.选中搜索引擎 == null && engines.size > 0) state.选中搜索引擎 = engines[0]
        }
    }

    Row(Modifier.fillMaxWidth()
        .padding(horizontal = 5.dp)
        .height(50.dp)
        .background(MaterialTheme.colorScheme.surface),
        verticalAlignment = Alignment.CenterVertically) {
        // 输入关键词显示搜索引擎列表
        if (state.显示搜索引擎){
            LazyRow(Modifier.fillMaxWidth()) {
                items(engines){
                    val sel = it.id == state.选中搜索引擎?.id
                    水平标签(it.名称,sel){
                        state.切换引擎(it)
                    }
                }
            }
        }

        // 非关键词输入时显示网址输入提示
        else {
            LazyRow(Modifier.fillMaxWidth()) {
                items(listOf("http://","https://",".","www.",".com",".cn")){
                    水平标签(it){

                        state.插入内容(it)
                    }
                }
            }
        }
    }

}

@Composable
private fun 输入法视图(state: 详情输入小窗页面状态){
    // 跟随虚拟键盘高度
    Spacer(Modifier.height(WindowInsets.ime.asPaddingValues().calculateBottomPadding()))
}

enum class 输入内容类型枚举{
    无,关键词,地址,原地址
}

@Composable
private fun 输入内容类型枚举.到文本() : String{
    return when (this ){
        输入内容类型枚举.无 -> "取消"
        输入内容类型枚举.关键词 -> "搜索"
        输入内容类型枚举.原地址 ->  "取消"
        输入内容类型枚举.地址 -> "进入"
    }
}